﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using System.Reflection;
using System.Collections.Concurrent;
using System.Linq;

public class WorkstationContext
{
    public string CurrentStationStatus { get; set; } // 当前工作站状态
    public ThreadLocal<string> NextStationStatus { get; set; } // 下一个工作站状态（ThreadLocal）
    private ThreadLocal<Workstation> stationStatus = new ThreadLocal<Workstation>(); // 记录工作站状态
    private ThreadLocal<int> _inex = new ThreadLocal<int>(() => -1); // 记录工作站状态
    public Workstation[] workstations; // 流水线上的工作站列表
    public void NextStation(Workstation wk)
    {
        stationStatus.Value = wk;
        _inex.Value++;
        List<string> Array = new List<string>();
        foreach (var a in workstations)
        {
            Part x=new Part(int.MaxValue);
             a?.buffer?.TryPeek(out   x);

            var str = $"buffer:{a?.buffer?.Count} " +
                      $"name:{a?.name} " +
                      $"IndexId:{x?.IndexId} " +
                      $"CurrentPart:{a?.CurrentPart?.IndexId}";
            Array.Add(str);
        }

        Debug.WriteLine(string.Join("\r\n", Array));
        Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}:{_inex.Value}");
    }
}
public class Part
{
    public int IndexId { get; set; }
    public Dictionary<string, TimeSpan> WorkstationTimes { get; set; } // 经过的工作站用时

    public Part(int indexId)
    {
        IndexId = indexId;
        WorkstationTimes = new Dictionary<string, TimeSpan>();
    }
}

public class Workstation
{
    public ConcurrentQueue<Part> buffer; // 缓存区
    public string name;
    private Workstation nextWorkstation;
    private readonly WorkstationContext _workstationContext;
    private readonly int _delay;
    private Random random;
    private string stationStatus; // 记录工作站状态
    private readonly WorkerTaskScheduler WorkerTaskScheduler = new WorkerTaskScheduler();
    public Part CurrentPart;

    public Workstation(string name, Workstation nextWorkstation, WorkstationContext workstationContext, int delay = 1000)
    {
        this.name = name;
        this.nextWorkstation = nextWorkstation;
        _workstationContext = workstationContext;
        _delay = delay;
        buffer = new ConcurrentQueue<Part>();
        random = new Random(GetHashCode());
        stationStatus = "闲置的"; // 初始状态为空闲
    }

    public bool HasPartInBuffer()
    {
        return buffer.Count > 0;
    }

    public void AddPartToBuffer(Part part)
    {
        buffer.Enqueue(part);
    }

    public Task ProcessPartAsync()
    {
        Task t = new Task(() =>
        {

            while (true)
            {
                int indexA = 0;
                if (HasPartInBuffer())
                {

                    buffer.TryDequeue(out var rsult);
                    CurrentPart = rsult;
                    int processingTime = _delay;// random.Next(2000, 5000); // 随机生成处理时间
                    stationStatus = "Working"; // 设置工作站状态为工作中
                    Task.Delay(processingTime).Wait(); // 模拟工作站处理时间
                    stationStatus = "闲置的"; // 设置工作站状态为空闲
                    CurrentPart.WorkstationTimes[name] = TimeSpan.FromMilliseconds(processingTime); // 记录工作站用时
            
                    if (nextWorkstation != null)
                    {
                        int index = 0;
                        while (nextWorkstation.HasPartInBuffer())
                        {

                            index++;
                            Task.Delay(100).Wait(); // 如果缓存区为空，等待一段时间后重试
                        }

                        if (index != 0)
                        {
                            Console.WriteLine($"下站 {nextWorkstation.name} 阻塞。 index:{index}");
                        }

                        nextWorkstation.AddPartToBufferAsync(CurrentPart);
                    }
                    else
                    {
                        // 如果是最后一个工作站，输出到下料区域
                        CurrentPart.WorkstationTimes["Output"] = new TimeSpan(); // 模拟输出到下料区域的时间
                        Console.WriteLine($"Part {CurrentPart.IndexId} 完成并输出到卸载区域。");

                    }
                    _workstationContext.NextStation(this);
                    PrintDebugInfo(); // 打印调试信息

                }
                else
                {
                    Task.Delay(100).Wait(); // 如果缓存区为空，等待一段时间后重试
                    indexA++;
                }

                if (indexA != 0 && nextWorkstation != null)
                {
                    //  Console.WriteLine($"前站 阻塞。 index:{indexA}   {name}");
                }

            }
        });

        t.Start(WorkerTaskScheduler);

        return t;

    }

    public void AddPartToBufferAsync(Part part)
    {
        AddPartToBuffer(part);


        //Task t = new Task(() => {  });
        //t.Start();

        //t.Start(WorkerTaskScheduler);
        //await t;
        ///  await Task.Run(() => AddPartToBuffer(part));
    }

    private void PrintDebugInfo()
    {
        Console.WriteLine($"{name} 工作站状态: {stationStatus} ");
        Console.WriteLine($"{name} 工作站缓冲区状态: {(HasPartInBuffer() ? "占用" : "空的")}  Next工作站:{nextWorkstation?.name}");
        //if (nextWorkstation != null)
        //{
        //    Console.WriteLine($"Next工作站:{nextWorkstation.name} 工作站缓冲区状态: {(nextWorkstation.HasPartInBuffer() ? "占用" : "空的")}");
        //}

        //while (nextWorkstation?.HasPartInBuffer() == true) 
        //{

        //      Task.Delay(100).Wait() ; // 如果缓存区为空，等待一段时间后重试
        //}

        Console.WriteLine();
    }
}

public class AssemblyLine
{
    private Workstation[] workstations; // 流水线上的工作站列表

    public AssemblyLine()
    {
        var WorkstationContext = new WorkstationContext();
        // 初始化流水线上的工作站
        Workstation workstation5 = new Workstation("Workstation5", null, WorkstationContext, 2000);
        Workstation workstation4 = new Workstation("Workstation4", workstation5, WorkstationContext, 5000);
        Workstation workstation3 = new Workstation("Workstation3", workstation4, WorkstationContext, 1000);
        Workstation workstation2 = new Workstation("Workstation2", workstation3, WorkstationContext, 3900);
        Workstation workstation1 = new Workstation("Workstation1", workstation2, WorkstationContext, 1000);

        workstations = new Workstation[] { workstation1, workstation2, workstation3, workstation4, workstation5 };
        WorkstationContext.workstations = workstations;
    }

    public async Task StartAssemblyLineAsync()
    {
        try
        {


            List<Task> tasks = new List<Task>();

            foreach (var workstation in workstations)
            {
                tasks.Add(workstation.ProcessPartAsync());
            }

            await Task.WhenAll(tasks);

        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public async Task StartPartsFlowAsync(int numParts)
    {
        List<Task> tasks = new List<Task>();

        foreach (var workstation in workstations)
        {
            tasks.Add(workstation.ProcessPartAsync());
        }



        for (int i = 0; i < numParts; i++)
        {
            Part part = new Part(i + 1);
            Debug.WriteLine($"add:{part.IndexId}");
            workstations[0].AddPartToBufferAsync(part);
            Task.Delay(1500).Wait(); // 模拟Part连续流入的间隔
            while (workstations[0].HasPartInBuffer())
            {
                Task.Delay(500).Wait(); ; // 模拟Part连续流入的间隔
            }
            Task.Delay(500).Wait(); ; // 模拟Part连续流入的间隔
        }
        await Task.WhenAll(tasks);
    }
}

public class Program
{
    public static async Task Main(string[] args)
    {
        AssemblyLine assemblyLine = new AssemblyLine();

        await assemblyLine.StartPartsFlowAsync(6); // 流入10个配件
    }
}




public class WorkerTaskScheduler : TaskScheduler, IDisposable
{

    //public static new TaskScheduler Current { get; } = new SpecTaskScheduler();
    //public static new TaskScheduler Default { get; } = Current;

    private readonly BlockingCollection<Task> m_queue = new BlockingCollection<Task>();

    private Thread _runThread;

    public WorkerTaskScheduler()
    {
        _runThread = new Thread(Run);
        _runThread.IsBackground = true;//设为为后台线程，当主线程结束时线程自动结束
        _runThread.Start();
        _runThread.Priority = ThreadPriority.Highest;
    }

    private void Run()
    {
        //Console.WriteLine($"SpecTaskScheduler, ThreadID: {Thread.CurrentThread.ManagedThreadId}");
        Task t;
        while (m_queue.TryTake(out t, Timeout.Infinite))
        {
            TryExecuteTask(t);//在当前线程执行Task
        }
    }

    protected override IEnumerable<Task> GetScheduledTasks()
    {
        return m_queue;
    }

    protected override void QueueTask(Task task)
    {
        m_queue.Add(task);//t.Start(MyTaskScheduler.Current)时，将Task加入到队列中
    }

    //当执行该函数时，程序正在尝试以同步的方式执行Task代码
    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
        return false;
    }

    public void Dispose()
    {
        _runThread.Abort();
        //  m_queue.CompleteAdding();
        // m_queue.Dispose();

    }
}